import types
from sphinx.util.docstrings import prepare_docstring
from sphinx.util import force_decode
try:
    # Sphinx < 1.0
    from sphinx.directives.desc import ClasslikeDesc as PyClasslike
except ImportError:
    from sphinx.domains.python import PyClasslike
from sphinx.ext import autodoc

class InterfaceDesc(PyClasslike):
    def get_index_text(self, modname, name_cls):
        return '%s (interface in %s)' % (name_cls[0], modname)


from forest.tool import search_tools
from forest.command import search_commands
search_tools()
search_commands()

from forest.command import command_registry


class InterfaceDocumenter(autodoc.ClassDocumenter):
    
    """
    Specialized Documenter directive for zope interfaces.
    """
    objtype = "command"
    # Must be a higher priority than ClassDocumenter
    member_order = 10
    directivetype = 'command'

    @classmethod
    def can_document_member(cls, member, membername, isattr, parent):
        # we don't want to be automaticaly used
        return False
        
    def __init__(self, *args, **kwargs):
        #args[1] = 'test'
        #super(InterfaceDocumenter, self).__init__(directive, name, indent)
        
        super(InterfaceDocumenter, self).__init__(*args, **kwargs)
        self.options.show_inheritance=True


    def import_object(self):
        self.object= command_class = inspect.getmodule(command_registry[self.name])
        return self.object
    
    '''
    @classmethod
    def can_document_member(cls, member, membername, isattr, parent):
        return isinstance(member, types.ClassType) and \
                issubclass(member, Interface)

    def add_directive_header(self, sig):
        if self.doc_as_attr:
            self.directivetype = 'attribute'
        autodoc.Documenter.add_directive_header(self, sig)

        # add inheritance info, if wanted
        bases=[base for base in self.object.__bases__ if base is not Interface]
        if not self.doc_as_attr and self.options.show_inheritance and bases:
            self.add_line(u'', '<autodoc>')
            bases = [u':class:`%s.%s`' % (b.__module__, b.getName())
                     for b in bases]
            self.add_line(u'   Extends: %s' % ', '.join(bases),
                          '<autodoc>')

    def format_args(self):
        return ""

    def document_members(self, all_members=True):
        oldindent = self.indent
        members = self.object.namesAndDescriptions()
        if self.options.members is not autodoc.ALL:
            specified = []
            for line in (self.options.members or []):
                specified.extend(line.split())
            mapping = dict(members)
            members = [(x, mapping[x]) for x in specified]
        member_order = (self.options.member_order or 
                        self.env.config.autodoc_member_order)
        if member_order == 'alphabetical':
            members.sort()
        if member_order == 'groupwise':
            # sort by group; relies on stable sort to keep items in the
            # same group sorted alphabetically
            members.sort(key=lambda e:
                                getattr(e[1], 'getSignatureString',
                                        None) is not None)
        elif member_order == 'bysource' and self.analyzer:
            # sort by source order, by virtue of the module analyzer
            tagorder = self.analyzer.tagorder
            name = self.object.__name__
            def keyfunc(entry):
                return tagorder.get('%s.%s' % (name, entry[0]), len(tagorder))
            members.sort(key=keyfunc)

        for name, desc in members:
            self.add_line(u'', '<autointerface>')
            sig = getattr(desc, 'getSignatureString', None)
            if sig is None:
                self.add_line(u'.. attribute:: %s' % name, '<autointerface>')
            else:
                self.add_line(u'.. method:: %s%s' % (name, sig()),
                              '<autointerface>')
            doc = desc.getDoc()
            if doc:
                self.add_line(u'', '<autointerface>')
                self.indent += self.content_indent
                sourcename = u'docstring of %s.%s' % (self.fullname, name)
                docstrings=[prepare_docstring(force_decode(doc, None))]
                for i, line in enumerate(self.process_doc(docstrings)):
                    self.add_line(line, sourcename, i)
                self.add_line(u'', '<autointerface>')
                self.indent = oldindent'''

def find_path(root, leaf):
    for key in dir(root):
        attr = getattr(root, key)
        if attr.__class__ is leaf:
            return [key]
            
        if isinstance(attr, WebServicesController):
            path = find_path(attr, leaf)
            if path is not None:
                return [key] + path
                
                
class InterfaceDocumenter(autodoc.ClassDocumenter):
    objtype = "command"
    directivetype = "class"

    def get_index_text(self, modname, name_cls):
        path = name_cls[0]
        pathi = path.rfind('.')
        path = path[:pathi]
        
        classname = name_cls[0]
        classnamei = classname.rfind('.')
        classname = classname[classnamei+1:]
        
        if path not in sys.modules:
            return ''
            
        return unicode(getattr(sys.modules[path], classname).__register__)
        
    def add_directive_header(self, sig):
        """Add the directive header and options to the generated content."""
        domain = getattr(self, 'domain', 'py')
        directive = getattr(self, 'directivetype', self.objtype)
        name = self.format_name()
        #  directive,
        
        plugname = self.object.__register__
        plugname = plugname[plugname.find('.')+1:]
        self.add_line(u'.. %s:class:: %s' % (domain, plugname),
                      '<autodoc>')
        if self.options.noindex:
            self.add_line(u'   :noindex:', '<autodoc>')
        if self.objpath:
            # Be explicit about the module, this is necessary since .. class::
            # etc. don't support a prepended module name
            self.add_line(u'   :module: %s' % self.modname, '<autodoc>')
            
    def parse_name(self):
        """
        Determine what module to import and what attribute to document.

        Returns True and sets *self.modname*, *self.objpath*, *self.fullname*,
        *self.args* and *self.retann* if parsing and resolving was successful.
        """
        # first, parse the definition -- auto directives for classes and
        # functions can contain a signature which is then used instead of
        # an autogenerated one
        try:
            explicit_modname, path, base, args, retann = \
                 autodoc.py_ext_sig_re.match(self.name).groups()
        except AttributeError:
            self.directive.warn('invalid signature for auto%s (%r)' %
                                (self.objtype, self.name))
            return False

        # support explicit module and class name separation via ::
        if explicit_modname is not None:
            modname = explicit_modname[:-2]
            parents = path and path.rstrip('.').split('.') or []
        else:
            modname = None
            parents = []

        self.modname, self.objpath = self.resolve_name(modname, parents, path, base)

        if not self.modname:
            return False

        self.args = args
        self.retann = retann
        self.name = '1234'#(self.modname or '') + \
                        #(self.objpath and '.' + '.'.join(self.objpath) or '')
        return True
       
import sys
import sphinx
#class InterfaceDirective(sphinx.ext.autodoc.AutoDirective):
class InterfaceDirective(sphinx.domains.python.PyClasslike):
    r"""An `'interface'` directive."""
    def get_index_text(self, modname, name_cls):
        path = name_cls[0]
        pathi = path.rfind('.')
        path = path[:pathi]
        
        classname = name_cls[0]
        classnamei = classname.rfind('.')
        classname = classname[classnamei+1:]
        
        if path not in sys.modules:
            return ''
            
        return unicode(getattr(sys.modules[path], classname).__register__)
        
        return '%s' % name_cls[1]
        return '%s (%s interface)' % (name_cls[0], modname)

def setup(app):
    pass
    #app.add_autodoc_attrgetter(zope.interface.interface.InterfaceClass,
    #                           interface_getattr)
    #app.add_autodocumenter(InterfaceDocumenter)
    #app.add_autodocumenter(InterfaceAttributeDocumenter)
    #app.add_autodocumenter(InterfaceMethodDocumenter)
    #
    #
    #domain.object_types['interface'] = sphinx.domains.python.ObjType(
    #    l_('interface'), 'interface', 'obj')
    #
    #domain.roles['interface'] = sphinx.domains.python.PyXRefRole()



def setup(app):
    #try:
    #    app.add_directive_to_domain('py', 'autocommand', InterfaceDesc)
    #except AttributeError:
    #    # Sphinx < 1.0
    #    app.add_directive('autocommand', InterfaceDesc)
    app.add_autodocumenter(InterfaceDocumenter)
    domain = sphinx.domains.python.PythonDomain
    
    #domain.directives['autocommand'] = InterfaceDirective
    #domain.roles['autocommand'] = sphinx.domains.python.PyXRefRole()
